package sxr.common.aspect;


import cn.thinkjoy.springboot.vuc.common.Enum.BusinessExceptionEnum;
import cn.thinkjoy.springboot.vuc.common.annotation.ApiCheckAnnotation;
import cn.thinkjoy.springboot.vuc.exception.BusinessException;
import cn.thinkjoy.springboot.vuc.service.IAppDetailsService;
import cn.thinkjoy.springboot.vuc.service.IDataPermService;
import cn.thinkjoy.springboot.vuc.utils.ConstantUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * Created by xufei on 2019/10/29.
 */
@Aspect
@Order(-99) // 控制多个Aspect的执行顺序，越小越先执行, 当然也可以不写这注解, 对于写和不写@order的两个切面, 有@order的优先于无@order的执行; 都有@order时, 越小越执先执行
@Component
public class ApiCheckAspect {

    private static final Logger logger = LoggerFactory.getLogger(ApiCheckAspect.class);

    @Autowired
    private IAppDetailsService appDetailsService;
    @Autowired
    private IDataPermService dataPermService;

    @Pointcut("@annotation(cn.thinkjoy.springboot.vuc.common.annotation.ApiCheckAnnotation)")
    public void ApiCheckPointCat(){
    }

    @Around("ApiCheckPointCat()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        //执行方法
        apiCheckCore(point);
        Object object=point.proceed();
        return object;
    }

    /**
     * 接口权限验证
     * 1、验证appId
     * 2、根据接口配置的验证级别，验证用户是否有权限
     * @param joinPoint
     * @throws InterruptedException
     */
    void apiCheckCore(ProceedingJoinPoint joinPoint) throws InterruptedException {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();

        Object[] args = joinPoint.getArgs();
        //1、验证appId是否存在
        String appId = (String) args[1];
        Boolean appCheck=appDetailsService.checkAppId(appId);
        if(appCheck==false){
            throw new BusinessException(BusinessExceptionEnum.AppIdError);
        }

        //2、根据接口配置的验证级别，验证用户是否有权限
        ApiCheckAnnotation apiCheckParam = method.getAnnotation(ApiCheckAnnotation.class);
        //需要验证的参数位置
        int paramLocation=-1;
        //请求的参数名称
        String[] parameterNames = signature.getParameterNames();
        for (int i =0 ,len=parameterNames.length;i < len ;i++){
            if(parameterNames[i].equals(apiCheckParam.checkType().getName())){
                paramLocation=i;
                break;
            }
        }
        if(paramLocation==-1){
            throw new BusinessException(BusinessExceptionEnum.ParamNotFound);
        }


        String operId = (String) args[0];
        String checkCode= (String) args[paramLocation];
        String schoolCode=null;
        //如果是年级权限，需要获取对应学校编码
        if(ConstantUtils.ApiCheckType.GTADE==apiCheckParam.checkType().getCode()) {
            int schoolCodeLocation = -1;
            for (int i = 0, len = parameterNames.length; i < len; i++) {
                if (parameterNames[i].equals("schoolCode")) {
                    schoolCodeLocation = i;
                    break;
                }
            }
            if (schoolCodeLocation == -1) {
                throw new BusinessException(BusinessExceptionEnum.ParamNotFound.getCode(), "权限校验,验证参数schoolCode不能为空");
            }
            schoolCode = (String) args[schoolCodeLocation];
        }
        //权限验证
        Boolean apiCheck=dataPermService.checkDataPerm(apiCheckParam.checkType().getCode(),operId,schoolCode,checkCode);
        if(apiCheck!=true){
            throw new BusinessException(BusinessExceptionEnum.NoPermission);
        }
    }
}